package net.yxsoft.kit;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * sm3国密加密
 * @Author: wj
 * @Date: 2022/3/13 14:54
 */
public class Sm3Utils {

  private static final String ENCODING = "UTF-8";
  private static final String PARAMSTR = "appId=5da1df777687415087284a6acb15c469&cardType=1&editable=1&idCard={idCard}&returnUrl={returnUrl}&type=h5&userName={userName}";

  static {
    Security.addProvider(new BouncyCastleProvider());
  }

  /**
   * 数据签名
   * @param appKey
   * @param idCard
   * @param userName
   * @param returnUrl
   * @return
   */
  public static String encrypt(String appKey, String idCard, String userName, String returnUrl){
    return sign(PARAMSTR.replace("{idCard}", idCard).replace("{returnUrl}", returnUrl).replace("{userName}", userName) + "&" + appKey);
  }


  /**
   * 数据签名
   * @param paramStr 要加密的源数据
   * @return
   */
  public static String encrypt(String paramStr){

    return sign(paramStr);
  }

  /**
   * 根据私钥数据签名
   * @param params 要加密的参数
   * @param privatekey 私钥
   * @return
   */
  public static String encryptByprivatekey( Map<String, String> params,String privatekey){
    String[] keys = params.keySet().toArray(new String[0]);
    Arrays.sort(keys);
    StringBuilder query = new StringBuilder();
    for (String key : keys) {
      if ("sign".equals(key)) {
        continue;
      }

      String value = String.valueOf(params.get(key));
      query.append(key).append("=").append(value).append("&");
    }
    query.append(privatekey);

    return sign(query.toString());
  }

  /**
   * 数据签名
   * @param paramStr 要加密的源数据
   * @return
   */
  public static String sign(String paramStr){
    // 将返回的hash值转换成16进制字符串
    String resultHexString = "";
    try {
      // 将字符串转换成byte数组
      byte[] srcData = paramStr.getBytes(ENCODING);
      // 调用hash()
      byte[] resultHash = hash(srcData);
      // 将返回的hash值转换成16进制字符串
      resultHexString = ByteUtils.toHexString(resultHash);
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return resultHexString.toUpperCase();
  }


  /**
   * 返回长度=32的byte数组
   * @explain 生成对应的hash值
   * @param srcData
   * @return
   */
  public static byte[] hash(byte[] srcData) {
    SM3Digest digest = new SM3Digest();
    digest.update(srcData, 0, srcData.length);
    byte[] hash = new byte[digest.getDigestSize()];
    digest.doFinal(hash, 0);
    return hash;
  }

  public static boolean verify(String srcStr, String sm3HexString) {
    boolean flag = false;
    try {
      byte[] srcData = srcStr.getBytes(ENCODING);
      byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
      byte[] newHash = hash(srcData);
      if (Arrays.equals(newHash, sm3Hash))
        flag = true;
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    return flag;
  }


  public static void main(String [] agr){
    Map<String, String> params=new HashMap<>();
    String tm="1690257554878";
    params.put("publicKey","MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJE65fDAfpfb9FhTJm7jgx96BE1KJOhrB3f2NyJv1kn9UsqquTKDXQZAeaT2Or0XA5KwXl0TA7Eq0DuHljSRwwcCAwEAAQ==");
    params.put("eimSource","s_test");
    params.put("timestamp",tm);
    params.put("attrStr","|test|test|12|331|test||||||||||||||||||||||||||||||||||||||||||");
    String privatekey ="77709dd9680d932609d8af8d11b9d16e433ad55ee54a5b7e235610463968be4b"; //ApiService.me.getPrivateKeynfo(String.valueOf(params.get("publicKey")));

    System.out.println("签名="+  encryptByprivatekey(params,privatekey));

/*    Map<String, String> params=new HashMap<>();
    String tm="1690257554878";
    params.put("loginId","ttt");
    params.put("password","mjy123456");
    params.put("eimSource","s_test");
    params.put("timestamp",tm);
    params.put("attrStr","|test|test|12|331|test||||||||||||||||||||||||||||||||||||||||||");

    String[] keys = params.keySet().toArray(new String[0]);
    Arrays.sort(keys);
    StringBuilder query = new StringBuilder();
    for (String key : keys) {
      if ("sign".equals(key)) {
        continue;
      }

      String value = String.valueOf(params.get(key));
      query.append(key).append("=").append(value).append("&");
    }
    query.deleteCharAt(query.length() - 1);
    System.out.println("签名="+ Sm3Utils.encrypt(query.toString()).toUpperCase());*/
  }

}
